﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
using System.Threading.Tasks;
using System.Xml.Linq;
using CoreShop.Library;
using CoreShop.Model;
using CoreShop.Repository;
using CoreShop.Services.Services.Report;
using SqlSugar;


namespace CoreShop.Services
{
    /// <summary>
    /// 接口实现
    /// </summary>
    public class corecmsfoodorderclassServices : Repository<corecmsfoodorderclass>, IcorecmsfoodorderclassServices
    {
        #region 实现重写增删改查操作==========================================================

        /// <summary>
        /// 重写异步插入方法
        /// </summary>
        /// <param name="entity">实体数据</param>
        /// <returns></returns>
        public bool InsertAsync(corecmsfoodorderclass entity)
        {
            return base.Change<corecmsfoodorderclass>().Insert(entity);
        }
        public bool InsertOrUpdate(List<corecmsfoodorderclass> entity)
        {
            return base.InsertOrUpdate(entity);
        }
        /// <summary>
        /// 重写异步更新方法方法
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool UpdateAsync(corecmsfoodorderclass entity)
        {
            return base.Change<corecmsfoodorderclass>().Update(a => new corecmsfoodorderclass()
            {
                classNumber = entity.classNumber,
                sysUserId = entity.sysUserId,
                marketId = entity.marketId,
                starDate = entity.starDate,
                endDate = entity.endDate,
                createTime = entity.createTime,
                classOff = entity.classOff,
                isUpload = entity.isUpload,
                cashBoxMoney = entity.cashBoxMoney
            }, a => a.id == entity.id);
        }

        /// <summary>
        /// 重写异步更新方法方法
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool UpdateAsync(List<corecmsfoodorderclass> entity)
        {
            bool returnKey = true;
            foreach (var item in entity)
            {
                returnKey = base.Change<corecmsfoodorderclass>().Update(a => new corecmsfoodorderclass()
                {
                    classNumber = item.classNumber,
                    sysUserId = item.sysUserId,
                    marketId = item.marketId,
                    starDate = item.starDate,
                    endDate = item.endDate,
                    createTime = item.createTime,
                    classOff = item.classOff,
                    isUpload = item.isUpload,
                    cashBoxMoney = item.cashBoxMoney
                }, a => a.id == item.id);
            }
            return returnKey;
        }

        /// <summary>
        /// 重写删除指定ID的数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool DeleteByIdAsync(long id)
        {
            return base.Change<corecmsfoodorderclass>().DeleteById(id);
        }

        /// <summary>
        /// 重写删除指定ID集合的数据(批量删除)
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public bool DeleteByIdsAsync(int[] ids)
        {
            bool returnKey = true;
            foreach (int id in ids)
            {
                returnKey = base.Change<corecmsfoodorderclass>().DeleteById(id);
            }
            return returnKey;
        }

        #endregion

        #region 获取缓存的所有数据==========================================================

        /// <summary>
        /// 获取缓存的所有数据
        /// </summary>
        /// <returns></returns>
        public List<corecmsfoodorderclass> GetCaChe()
        {
            return base.GetList();
        }

        #endregion

        #region 根据条件查询分页数据
        /// <summary>
        /// 根据条件查询分页数据
        /// </summary>
        /// <param name="count"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="sName"></param>
        /// <returns></returns>
        public List<corecmsfoodorderclass> QueryPageAsync(ref int count, int? pageIndex, int? pageSize, string sName)
        {
            List<corecmsfoodorderclass> lst = new List<corecmsfoodorderclass>();
            var where = Expressionable.Create<corecmsfoodorderclass>();
            if (!string.IsNullOrEmpty(sName))
            {
                where = where.And(a => a.classNumber.Contains(sName));
            }
            if (pageIndex >= 1 && pageSize > 0)
            {
                lst = base.AsQueryable().WhereIF(true, where.ToExpression())
                    .ToPageList((int)pageIndex, (int)pageSize, ref count)
                    .OrderBy(a => a.id).ToList();
            }
            else
            {
                lst = base.AsQueryable().WhereIF(true, where.ToExpression()).OrderBy(a => a.id).ToList();
            }

            return lst;
        }
        #endregion

        public ClassDataDto GetClassData(long classId)
        {
            ClassDataDto classModel = new corecmsfoodorderclassServices().AsQueryable()
                .LeftJoin<corecmsfoodordermaster>((c, o) => c.id == o.classId)
                .LeftJoin<corecmsstoremarket>((c, o, m) => c.marketId == m.id)
                .LeftJoin<sysuser>((c, o, m, s) => c.sysUserId == s.id)
                .GroupBy((c, o, m, s) => c.id)
                .Where((c, o, m, s) => c.id == classId)
                .Select((c, o, m, s) => new ClassDataDto
                {
                    userName = s.userName,
                    classNumber = c.classNumber,
                    createTime=c.createTime,
                    starDate = SqlFunc.AggregateMin(o.orderDate),
                    endDate = SqlFunc.AggregateMax(o.orderDate),
                    marketName = m.name,
                    allCount = SqlFunc.AggregateCount(o.orderNo),
                    allPerson = SqlFunc.AggregateSum(o.person),
                    allFoodCount = SqlFunc.AggregateSum(o.sumQuantity),
                    refundFoodCount = 0,
                    sumShouldAmount = SqlFunc.AggregateSum(o.sumAmount) + SqlFunc.AggregateSum(o.sumFeedAmount)+ SqlFunc.AggregateSum(o.sumTaskAmount),
                    sumRealAmount = SqlFunc.AggregateSum(o.sumRealAmount) + SqlFunc.AggregateSum(o.sumFeedAmount) + SqlFunc.AggregateSum(o.sumTaskAmount),
                    sumDiscountAmount = SqlFunc.AggregateSum(o.sumDiscountAmount),
                    sumAllAmount = SqlFunc.AggregateSum(o.sumAllAmount),
                    sumFloorAmount = SqlFunc.AggregateSum(o.sumFloorAmount),
                    sumFreeAmount = SqlFunc.AggregateSum(o.sumFreeAmount),
                    sunReduceAmount = SqlFunc.AggregateSum((o.sumRealAmount+ o.sumFeedAmount+ o.sumTaskAmount)- o.sumAllAmount),
                    settlementUn = c.settlementUn,
                    Sum_consumeCount = 0,
                    sum_consumeAmount = 0,
                    cashBoxMoney = c.cashBoxMoney,
                    cashSumAmount = 0,
                    cashAllAmount = 0,
                }).With(SqlWith.NoLock).Single();//sunReduceAmount = SqlFunc.AggregateSum(o.sumReduceAmount),

            if (classModel == null) return null;
            if (classModel.allCount==0)//无订单
            {
                classModel.starDate = classModel.createTime;
                classModel.endDate = DateTime.Now; 
            }

            List<Consumption> ConsumptionList = new corecmsfoodorderclassServices().AsQueryable()
                .InnerJoin<corecmsfoodordermaster>((c, m) => m.classId == c.id)
                .InnerJoin<corecmsfoodorderpayment>((c, m, y) => m.orderId == y.orderId)
                .InnerJoin<corecmspayments>((c, m, y, s) => s.id == y.paymentId)
                .Where((c, m, y, s) => c.id == classId)
                .GroupBy((c, m, y, s) => s.id)
                .Select((c, m, y, s) => new Consumption
                {
                    paymentId = y.paymentId,
                    payMentName = s.name,
                    payCount = SqlFunc.AggregateSum(1),
                    Amount = SqlFunc.AggregateSum(y.payAmount),
                }).ToList();

            classModel.Consumption = ConsumptionList;

            //会员充值
            var where = Expressionable.Create<corecmsfoodorderclass, corecmsuserbalance, corecmspayments>();
            where = where.And((c, b, s) => c.id == classId);
            where = where.And((c, b, s) => b.type == (int)Library.GlobalEnumVars.UserBalanceTypes.Deposit || b.type == (int)Library.GlobalEnumVars.UserBalanceTypes.DepositRefund);
            where = where.And((c, b, s) => b.payStatus == (int)GlobalEnumVars.OrderPayStatus.IsPay);

            List <userDeposit> userRechargeList = new corecmsfoodorderclassServices().AsQueryable()
                .InnerJoin<corecmsuserbalance>((c, b) => c.id == b.classId)
                .InnerJoin<corecmspayments>((c, b, s) => s.id == b.paymentId)
                .Where(where.ToExpression()).GroupBy((c, b, s) => s.id)
                .Select((c, b, s) => new userDeposit
                {
                    paymentId = b.paymentId,
                    payMentName = s.name,
                    Count = SqlFunc.AggregateCount(b.id),
                    Amount = SqlFunc.AggregateSum(b.money) - SqlFunc.AggregateSum(b.giftAmount),
                    giftAmount = SqlFunc.AggregateSum(b.giftAmount)
                }).ToList();

            //现金支付
            var ConsumptionCash = ConsumptionList.Find(p => p.paymentId == (int)GlobalEnumVars.Payment.cash);
            if (ConsumptionCash != null) classModel.cashSumAmount += ConsumptionCash.Amount;
            
            var DepositCash = userRechargeList.Find(p => p.paymentId == (int)GlobalEnumVars.Payment.cash);
            if (DepositCash != null) classModel.cashSumAmount += DepositCash.Amount;

            classModel.cashAllAmount = classModel.cashBoxMoney + classModel.cashSumAmount;


            //退菜统计
            var refunds = new corecmsfoodorderclassServices().AsQueryable()
                .LeftJoin<corecmsfoodordermaster>((c, o) => c.id == o.classId)
                .LeftJoin<corecmsfoodorderdetail>((c, o, m) => o.orderId == m.orderId)
                .GroupBy((c, o, m) => c.id)
                .Where((c, o, m) => c.id == classId && m.dataType == (int)Library.GlobalEnumVars.OrderingDataType.Refund)
                .Select((c, o, m) => new ClassFoodType
                {
                    typeName = "",
                    typeQuantity = SqlFunc.AggregateSum(m.quantity),
                    typeAmount = SqlFunc.AggregateSum(m.amount),
                }).Single();
            if (refunds != null)
            {
                classModel.refundQuantity = refunds.typeQuantity;
                classModel.refundAmount = refunds.typeAmount;
            }

            var refundFoods = new corecmsfoodorderclassServices().AsQueryable()
                .LeftJoin<corecmsfoodordermaster>((c, o) => c.id == o.classId)
                .LeftJoin<corecmsfoodorderdetail>((c, o, m) => o.orderId == m.orderId)
                .GroupBy((c, o, m) => m.foodId)
                .Where((c, o, m) => c.id == classId && m.dataType == (int)Library.GlobalEnumVars.OrderingDataType.Refund)
                .Select((c, o, m) => new ClassFoodType
                {
                    typeName = m.foodId.ToString(),
                    typeQuantity = SqlFunc.AggregateCount(m.foodId),
                }).ToList();
            if (refunds != null) classModel.refundFoodCount = refundFoods.Count();

            //赠送统计
            var present = new corecmsfoodorderclassServices().AsQueryable()
                .LeftJoin<corecmsfoodordermaster>((c, o) => c.id == o.classId)
                .LeftJoin<corecmsfoodorderdetail>((c, o, m) => o.orderId == m.orderId)
                .GroupBy((c, o, m) => c.id)
                .Where((c, o, m) => c.id == classId && m.dataType == (int)Library.GlobalEnumVars.OrderingDataType.Present)
                .Select((c, o, m) => new TypeModel
                {
                    name = "赠送",
                    quantity = SqlFunc.AggregateSum(m.quantity),
                    amount = SqlFunc.AggregateSum(m.amount),
                }).Single();
            if (present != null)
            {
                classModel.presentCount = present.quantity;
                classModel.presentAmount = present.amount;
            }

            classModel.userDeposits = userRechargeList;

            if (classModel.allCount > 0) classModel.avgBillPrice = classModel.sumRealAmount / classModel.allCount;
            if (classModel.allPerson > 0) classModel.avgPersonPrice = classModel.sumRealAmount / classModel.allPerson;

            classModel.foodTypes = new corereportServices().GetClassFoodType(classId);

            classModel.payments = new List<ClassPayment>();
            List<corecmspayments> pms = new corecmspaymentsService().SelectDataAll();
            foreach (var item in pms)
            {
                var cons = ConsumptionList.Find(p => p.paymentId == item.id);
                var users = userRechargeList.Find(p => p.paymentId == item.id);
                if (cons != null || users != null)
                {
                    int payCount = cons != null ? cons.payCount : 0;
                    decimal conAmount = cons != null ? cons.Amount : 0;
                    decimal userAmount = users != null ? users.Amount : 0;
                    ClassPayment payment = new ClassPayment()
                    {
                        payName = item.name,
                        posAmount = conAmount,
                        depAmount = userAmount,
                        payCount = payCount,
                        allAmount = conAmount + userAmount
                    };
                    classModel.payments.Add(payment);
                    if (item.id == (int)GlobalEnumVars.Payment.balancepay)
                    {
                        classModel.Sum_consumeCount = payCount;
                        classModel.sum_consumeAmount = conAmount;
                    }
                }
            }

            //商品部门
            List<ClassDeparts> foodDeparts = new corecmsfoodordermasterServices().AsQueryable()
                .LeftJoin<corecmsfoodorderdetail>((a, b) => a.orderId == b.orderId)
                .LeftJoin<corecmsfood>((a, b, f) => b.foodId == f.id)
                .LeftJoin<corecmsdepartment>((a, b, f, t) => f.departId == t.id)
                .Where((a, b, f, t) => a.classId == classId && b.dataType != (int)GlobalEnumVars.OrderingDataType.Refund)
                .GroupBy((a, b, f, t) => new { t.id, t.name })
                .Select((a, b, f, t) => new ClassDeparts
                {
                    dptName = t.name,
                    dptQuantity = SqlFunc.AggregateSum(b.quantity),
                    dptAmount = SqlFunc.AggregateSum(b.allAmount),
                }).With(SqlWith.NoLock).ToList();

            foreach (var item in foodDeparts)
            {
                if (item.dptQuantity != 0) item.dptPrice = Math.Round(item.dptAmount / item.dptQuantity, 2);
            }
            classModel.departList = foodDeparts;
            classModel.sum_posAmount = classModel.Consumption.Sum(p => p.Amount);
            classModel.sum_depCount = classModel.userDeposits.Sum(p => p.Count);
            classModel.sum_depAmount = classModel.userDeposits.Sum(p => p.Amount);
            classModel.sum_allAmount = classModel.userDeposits.Sum(p => p.Amount) + classModel.Consumption.Sum(p => p.Amount);
            classModel.userGiftAmount = CommFunc.ConvertToDecimal(classModel.userDeposits.Sum(p => p.giftAmount));
            return classModel;
        }

        public List<corecmsfoodorderclass> QueryUpdataOrderClass()
        {
            List<corecmsfoodorderclass> userRechargeList = new corecmsfoodorderclassServices().AsQueryable()
                .LeftJoin<corecmsstoremarket>((a, m) => a.marketId == m.id)
                .Where((a, m) => a.isUpload == false)
                .Select((a, m) => new corecmsfoodorderclass
                {
                    id=a.id,
                    storeId = a.storeId,
                    classNumber = a.classNumber,
                    sysUserId = a.sysUserId,
                    marketId = a.marketId,
                    markName = m.name,
                    starDate = a.starDate,
                    endDate = a.endDate,
                    createTime = a.createTime,
                    classOff = a.classOff,
                    isUpload = a.isUpload,
                    cashBoxMoney = a.cashBoxMoney
                }).ToList();
            return userRechargeList;
        }
    }
}